home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / include / glibmm-2.4 / glibmm / refptr.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-04-20  |  9.6 KB  |  342 lines

  1. // -*- c++ -*-
  2. #ifndef _GLIBMM_REFPTR_H
  3. #define _GLIBMM_REFPTR_H
  4.  
  5. /* $Id: refptr.h,v 1.4 2005/04/07 08:28:46 murrayc Exp $ */
  6.  
  7. /* Copyright 2002 The gtkmm Development Team
  8.  *
  9.  * This library is free software; you can redistribute it and/or
  10.  * modify it under the terms of the GNU Library General Public
  11.  * License as published by the Free Software Foundation; either
  12.  * version 2 of the License, or (at your option) any later version.
  13.  *
  14.  * This library is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17.  * Library General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU Library General Public
  20.  * License along with this library; if not, write to the Free
  21.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  */
  23.  
  24.  
  25. namespace Glib
  26. {
  27.  
  28. /** RefPtr<> is a reference-counting shared smartpointer.
  29.  *
  30.  * Some objects in gtkmm are obtained from a shared
  31.  * store. Consequently you cannot instantiate them yourself. Instead they
  32.  * return a RefPtr which behaves much like an ordinary pointer in that members
  33.  * can be reached with the usual <code>object_ptr->member</code> notation.
  34.  * Unlike most other smart pointers, RefPtr doesn't support dereferencing
  35.  * through <code>*object_ptr</code>.
  36.  *
  37.  * Reference counting means that a shared reference count is incremented each
  38.  * time a RefPtr is copied, and decremented each time a RefPtr is destroyed,
  39.  * for instance when it leaves its scope. When the reference count reaches
  40.  * zero, the contained object is deleted, meaning  you don't need to remember
  41.  * to delete the object.
  42.  *
  43.  * RefPtr<> can store any class that has reference() and unreference() methods.
  44.  * In gtkmm, that is anything derived from Glib::ObjectBase, such as
  45.  * Gdk::Pixmap.
  46.  *
  47.  * See the "Memory Management" section in the "Programming with gtkmm"
  48.  * book for further information.
  49.  */
  50. template <class T_CppObject>
  51. class RefPtr
  52. {
  53. public:
  54.   /** Default constructor
  55.    *
  56.    * Afterwards it will be null and use of -> will cause a segmentation fault.
  57.    */
  58.   inline RefPtr();
  59.   
  60.   /// Destructor - decrements reference count.
  61.   inline ~RefPtr();
  62.  
  63.   /// For use only by the ::create() methods.
  64.   explicit inline RefPtr(T_CppObject* pCppObject);
  65.  
  66.   /** Copy constructor
  67.    *
  68.    * This increments the shared reference count.
  69.    */
  70.   inline RefPtr(const RefPtr<T_CppObject>& src);
  71.  
  72.   /** Copy constructor (from different, but castable type).
  73.    *
  74.    * Increments the reference count.
  75.    */
  76.   template <class T_CastFrom>
  77.   inline RefPtr(const RefPtr<T_CastFrom>& src);
  78.  
  79.   /** Swap the contents of two RefPtr<>.
  80.    * This method swaps the internal pointers to T_CppObject.  This can be
  81.    * done safely without involving a reference/unreference cycle and is
  82.    * therefore highly efficient.
  83.    */
  84.   inline void swap(RefPtr<T_CppObject>& other);
  85.  
  86.   /// Copy from another RefPtr:
  87.   inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CppObject>& src);
  88.  
  89.   /** Copy from different, but castable type).
  90.    *
  91.    * Increments the reference count.
  92.    */
  93.   template <class T_CastFrom>
  94.   inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CastFrom>& src);
  95.  
  96.   /// Tests whether the RefPtr<> point to the same underlying instance.
  97.   inline bool operator==(const RefPtr<T_CppObject>& src) const;
  98.   
  99.   /// See operator==().
  100.   inline bool operator!=(const RefPtr<T_CppObject>& src) const;
  101.  
  102.   /** Dereferencing.
  103.    *
  104.    * Use the methods of the underlying instance like so:
  105.    * <code>refptr->memberfun()</code>.
  106.    */
  107.   inline T_CppObject* operator->() const;
  108.  
  109.   /** Test whether the RefPtr<> points to any underlying instance.
  110.    *
  111.    * Mimics usage of ordinary pointers:
  112.    * @code
  113.    *   if (ptr)
  114.    *     do_something();
  115.    * @endcode
  116.    */
  117.   inline operator bool() const;
  118.  
  119.   /// Set underlying instance to 0, decrementing reference count of existing instance appropriately.
  120.   inline void clear();
  121.  
  122.  
  123.   /** Dynamic cast to derived class.
  124.    *
  125.    * The RefPtr can't be cast with the usual notation so instead you can use
  126.    * @code
  127.    *   ptr_derived = RefPtr<Derived>::cast_dynamic(ptr_base);
  128.    * @endcode
  129.    */
  130.   template <class T_CastFrom>
  131.   static inline RefPtr<T_CppObject> cast_dynamic(const RefPtr<T_CastFrom>& src);
  132.  
  133.   /** Static cast to derived class.
  134.    *
  135.    * Like the dynamic cast; the notation is 
  136.    * @code
  137.    *   ptr_derived = RefPtr<Derived>::cast_static(ptr_base);
  138.    * @endcode
  139.    */
  140.   template <class T_CastFrom>
  141.   static inline RefPtr<T_CppObject> cast_static(const RefPtr<T_CastFrom>& src);
  142.  
  143.   /** Cast to non-const.
  144.    *
  145.    * The RefPtr can't be cast with the usual notation so instead you can use
  146.    * @code
  147.    *   ptr_unconst = RefPtr<UnConstType>::cast_const(ptr_const);
  148.    * @endcode
  149.    */
  150.   template <class T_CastFrom>
  151.   static inline RefPtr<T_CppObject> cast_const(const RefPtr<T_CastFrom>& src);
  152.  
  153. private:
  154.   T_CppObject* pCppObject_;
  155. };
  156.  
  157.  
  158. #ifndef DOXYGEN_SHOULD_SKIP_THIS
  159.  
  160. // RefPtr<>::operator->() comes first here since it's used by other methods.
  161. // If it would come after them it wouldn't be inlined.
  162.  
  163. template <class T_CppObject> inline
  164. T_CppObject* RefPtr<T_CppObject>::operator->() const
  165. {
  166.   return pCppObject_;
  167. }
  168.  
  169. template <class T_CppObject> inline
  170. RefPtr<T_CppObject>::RefPtr()
  171. :
  172.   pCppObject_ (0)
  173. {}
  174.  
  175. template <class T_CppObject> inline
  176. RefPtr<T_CppObject>::~RefPtr()
  177. {
  178.   if(pCppObject_)
  179.     pCppObject_->unreference(); // This could cause pCppObject to be deleted.
  180. }
  181.  
  182. template <class T_CppObject> inline
  183. RefPtr<T_CppObject>::RefPtr(T_CppObject* pCppObject)
  184. :
  185.   pCppObject_ (pCppObject)
  186. {}
  187.  
  188. template <class T_CppObject> inline
  189. RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CppObject>& src)
  190. :
  191.   pCppObject_ (src.pCppObject_)
  192. {
  193.   if(pCppObject_)
  194.     pCppObject_->reference();
  195. }
  196.  
  197. // The templated ctor allows copy construction from any object that's
  198. // castable.  Thus, it does downcasts:
  199. //   base_ref = derived_ref
  200. template <class T_CppObject>
  201.   template <class T_CastFrom>
  202. inline
  203. RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CastFrom>& src)
  204. :
  205.   // A different RefPtr<> will not allow us access to pCppObject_.  We need
  206.   // to add a get_underlying() for this, but that would encourage incorrect
  207.   // use, so we use the less well-known operator->() accessor:
  208.   pCppObject_ (src.operator->())
  209. {
  210.   if(pCppObject_)
  211.     pCppObject_->reference();
  212. }
  213.  
  214. template <class T_CppObject> inline
  215. void RefPtr<T_CppObject>::swap(RefPtr<T_CppObject>& other)
  216. {
  217.   T_CppObject *const temp = pCppObject_;
  218.   pCppObject_ = other.pCppObject_;
  219.   other.pCppObject_ = temp;
  220. }
  221.  
  222. template <class T_CppObject> inline
  223. RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(const RefPtr<T_CppObject>& src)
  224. {
  225.   // In case you haven't seen the swap() technique to implement copy
  226.   // assignment before, here's what it does:
  227.   //
  228.   // 1) Create a temporary RefPtr<> instance via the copy ctor, thereby
  229.   //    increasing the reference count of the source object.
  230.   //
  231.   // 2) Swap the internal object pointers of *this and the temporary
  232.   //    RefPtr<>.  After this step, *this already contains the new pointer,
  233.   //    and the old pointer is now managed by temp.
  234.   //
  235.   // 3) The destructor of temp is executed, thereby unreferencing the
  236.   //    old object pointer.
  237.   //
  238.   // This technique is described in Herb Sutter's "Exceptional C++", and
  239.   // has a number of advantages over conventional approaches:
  240.   //
  241.   // - Code reuse by calling the copy ctor.
  242.   // - Strong exception safety for free.
  243.   // - Self assignment is handled implicitely.
  244.   // - Simplicity.
  245.   // - It just works and is hard to get wrong; i.e. you can use it without
  246.   //   even thinking about it to implement copy assignment whereever the
  247.   //   object data is managed indirectly via a pointer, which is very common.
  248.  
  249.   RefPtr<T_CppObject> temp (src);
  250.   this->swap(temp);
  251.   return *this;
  252. }
  253.  
  254. template <class T_CppObject>
  255.   template <class T_CastFrom>
  256. inline
  257. RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(const RefPtr<T_CastFrom>& src)
  258. {
  259.   RefPtr<T_CppObject> temp (src);
  260.   this->swap(temp);
  261.   return *this;
  262. }
  263.  
  264. template <class T_CppObject> inline
  265. bool RefPtr<T_CppObject>::operator==(const RefPtr<T_CppObject>& src) const
  266. {
  267.   return (pCppObject_ == src.pCppObject_);
  268. }
  269.  
  270. template <class T_CppObject> inline
  271. bool RefPtr<T_CppObject>::operator!=(const RefPtr<T_CppObject>& src) const
  272. {
  273.   return (pCppObject_ != src.pCppObject_);
  274. }
  275.  
  276. template <class T_CppObject> inline
  277. RefPtr<T_CppObject>::operator bool() const
  278. {
  279.   return (pCppObject_ != 0);
  280. }
  281.  
  282. template <class T_CppObject> inline
  283. void RefPtr<T_CppObject>::clear()
  284. {
  285.   RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this
  286.   this->swap(temp);
  287. }
  288.  
  289. template <class T_CppObject>
  290.   template <class T_CastFrom>
  291. inline
  292. RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_dynamic(const RefPtr<T_CastFrom>& src)
  293. {
  294.   T_CppObject *const pCppObject = dynamic_cast<T_CppObject*>(src.operator->());
  295.  
  296.   if(pCppObject)
  297.     pCppObject->reference();
  298.  
  299.   return RefPtr<T_CppObject>(pCppObject);
  300. }
  301.  
  302. template <class T_CppObject>
  303.   template <class T_CastFrom>
  304. inline
  305. RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_static(const RefPtr<T_CastFrom>& src)
  306. {
  307.   T_CppObject *const pCppObject = static_cast<T_CppObject*>(src.operator->());
  308.  
  309.   if(pCppObject)
  310.     pCppObject->reference();
  311.  
  312.   return RefPtr<T_CppObject>(pCppObject);
  313. }
  314.  
  315. template <class T_CppObject>
  316.   template <class T_CastFrom>
  317. inline
  318. RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_const(const RefPtr<T_CastFrom>& src)
  319. {
  320.   T_CppObject *const pCppObject = const_cast<T_CppObject*>(src.operator->());
  321.  
  322.   if(pCppObject)
  323.     pCppObject->reference();
  324.  
  325.   return RefPtr<T_CppObject>(pCppObject);
  326. }
  327.  
  328. #endif /* DOXYGEN_SHOULD_SKIP_THIS */
  329.  
  330. /** @relates Glib::RefPtr */
  331. template <class T_CppObject> inline
  332. void swap(RefPtr<T_CppObject>& lhs, RefPtr<T_CppObject>& rhs)
  333. {
  334.   lhs.swap(rhs);
  335. }
  336.  
  337. } // namespace Glib
  338.  
  339.  
  340. #endif /* _GLIBMM_REFPTR_H */
  341.  
  342.